package cn.com.greatwall.flowable.rest;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;

import org.apache.commons.io.IOUtils;
import org.flowable.bpmn.constants.BpmnXMLConstants;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.engine.HistoryService;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.ProcessDefinition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import cn.com.greatwall.common.utils.SecurityUtils;
import cn.com.greatwall.flowable.config.CustomProcessDiagramGenerator;
import cn.com.greatwall.flowable.service.PermissionService;
import cn.com.greatwall.logging.annotation.Log;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;

/**
 * @Author herw
 * @Time 2020-09-24 13:28:27
 * @Version 1.0
 * @Description: TODO(用一句话描述该文件做什么)
 */
@RestController
@RequiredArgsConstructor
@Api(tags = "Flowable：流程实例图")
@RequestMapping("/flowable/processInstanceImage")
public class ProcessInstanceImageController {
    private final RepositoryService repositoryService;
    private final PermissionService permissionService;
    private final HistoryService historyService;
    private final RuntimeService runtimeService;
    private final ProcessEngineConfiguration processEngineConfiguration;

    @Log("获取流程实例图")
    @ApiOperation("获取流程实例图")
    @GetMapping
    @PreAuthorize("@el.check('job:list','user:list')")
    public ResponseEntity<String> image(@RequestParam String processInstanceId) {
        HistoricProcessInstance processInstance = permissionService.validateReadPermissionOnProcessInstance(
                SecurityUtils.getCurrentUserId().toString(), processInstanceId);
        ProcessDefinition pde = repositoryService.getProcessDefinition(processInstance.getProcessDefinitionId());
        if (pde == null || !pde.hasGraphicalNotation()) {
            throw new FlowableException("Process instance image is not found with id " + processInstanceId);
        }
        List<String> highLightedFlows = new ArrayList<>();
        List<String> highLightedActivities = new ArrayList<>();
        List<HistoricActivityInstance> allHistoricActivityIntances = historyService
                .createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list();
        allHistoricActivityIntances.forEach(historicActivityInstance -> {
            if (BpmnXMLConstants.ELEMENT_SEQUENCE_FLOW.equals(historicActivityInstance.getActivityType())) {
                highLightedFlows.add(historicActivityInstance.getActivityId());
            } else {
                highLightedActivities.add(historicActivityInstance.getActivityId());
            }
        });

        List<String> runningActivitiIdList = null;
        // 流程已结束
        if (processInstance != null && processInstance.getEndTime() != null) {
            runningActivitiIdList = Arrays.asList();
        } else {
            runningActivitiIdList = runtimeService.getActiveActivityIds(processInstanceId);
        }

        BpmnModel bpmnModel = repositoryService.getBpmnModel(pde.getId());
        CustomProcessDiagramGenerator diagramGenerator = (CustomProcessDiagramGenerator) processEngineConfiguration
                .getProcessDiagramGenerator();
        InputStream resource = diagramGenerator.generateCustomDiagram(bpmnModel, "png", highLightedActivities,
                runningActivitiIdList, highLightedFlows, processEngineConfiguration.getActivityFontName(),
                processEngineConfiguration.getLabelFontName(), processEngineConfiguration.getAnnotationFontName(),
                processEngineConfiguration.getClassLoader(), 1.0, true);
        HttpHeaders responseHeaders = new HttpHeaders();
        responseHeaders.setContentType(MediaType.IMAGE_PNG);
        try {
            return new ResponseEntity<>(Base64.getEncoder().encodeToString(IOUtils.toByteArray(resource)),
                    responseHeaders, HttpStatus.OK);
        } catch (Exception e) {
            throw new FlowableException("Process instance image read error", e);
        }
    }
}
